// 安全工具集合

// 加密算法类型
export type EncryptionAlgorithm = 'AES-256-GCM' | 'AES-256-CBC' | 'RSA-OAEP'

// 安全工具类
export class SecurityUtils {
  // Base64 编码
  static base64Encode(str: string): string {
    // #ifdef H5
    return btoa(unescape(encodeURIComponent(str)))
    // #endif
    // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || APP-PLUS
    // 在小程序和App中使用uni-app的API
    return uni.arrayBufferToBase64(uni.stringToArrayBuffer(str))
    // #endif
  }

  // Base64 解码
  static base64Decode(str: string): string {
    // #ifdef H5
    return decodeURIComponent(escape(atob(str)))
    // #endif
    // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || APP-PLUS
    return uni.arrayBufferToString(uni.base64ToArrayBuffer(str))
    // #endif
  }

  // 生成随机盐
  static generateSalt(length: number = 16): string {
    const chars =
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  }

  // 生成随机密钥
  static generateKey(length: number = 32): string {
    const chars =
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  }

  // 简单的XOR加密（适用于轻量级加密需求）
  static xorEncrypt(text: string, key: string): string {
    let result = ''
    for (let i = 0; i < text.length; i++) {
      result += String.fromCharCode(
        text.charCodeAt(i) ^ key.charCodeAt(i % key.length)
      )
    }
    return this.base64Encode(result)
  }

  // 简单的XOR解密
  static xorDecrypt(encryptedText: string, key: string): string {
    try {
      const decoded = this.base64Decode(encryptedText)
      let result = ''
      for (let i = 0; i < decoded.length; i++) {
        result += String.fromCharCode(
          decoded.charCodeAt(i) ^ key.charCodeAt(i % key.length)
        )
      }
      return result
    } catch (error) {
      throw new Error('Decryption failed')
    }
  }

  // 生成哈希值（简单实现）
  static async hash(
    text: string,
    algorithm: string = 'SHA-256'
  ): Promise<string> {
    // #ifdef H5
    if (
      typeof window !== 'undefined' &&
      window.crypto &&
      window.crypto.subtle
    ) {
      const encoder = new TextEncoder()
      const data = encoder.encode(text)
      const hashBuffer = await window.crypto.subtle.digest(algorithm, data)
      const hashArray = Array.from(new Uint8Array(hashBuffer))
      return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
    }
    // #endif

    // 降级方案：简单的哈希实现
    return this.simpleHash(text)
  }

  // 简单哈希实现（降级方案）
  private static simpleHash(str: string): string {
    let hash = 0
    if (str.length === 0) return hash.toString()

    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i)
      hash = (hash << 5) - hash + char
      hash = hash & hash // 转换为32位整数
    }

    return Math.abs(hash).toString(16)
  }

  // 验证密码强度
  static validatePasswordStrength(password: string): {
    score: number
    level: 'weak' | 'medium' | 'strong' | 'very-strong'
    suggestions: string[]
  } {
    const suggestions: string[] = []
    let score = 0

    // 长度检查
    if (password.length >= 8) {
      score += 1
    } else {
      suggestions.push('密码长度至少8位')
    }

    if (password.length >= 12) {
      score += 1
    }

    // 包含小写字母
    if (/[a-z]/.test(password)) {
      score += 1
    } else {
      suggestions.push('包含小写字母')
    }

    // 包含大写字母
    if (/[A-Z]/.test(password)) {
      score += 1
    } else {
      suggestions.push('包含大写字母')
    }

    // 包含数字
    if (/\d/.test(password)) {
      score += 1
    } else {
      suggestions.push('包含数字')
    }

    // 包含特殊字符
    if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
      score += 1
    } else {
      suggestions.push('包含特殊字符')
    }

    // 不包含常见弱密码模式
    const weakPatterns = [/123456/, /password/i, /qwerty/i, /abc123/i, /admin/i]

    if (!weakPatterns.some((pattern) => pattern.test(password))) {
      score += 1
    } else {
      suggestions.push('避免使用常见弱密码')
    }

    // 确定强度等级
    let level: 'weak' | 'medium' | 'strong' | 'very-strong'
    if (score <= 2) {
      level = 'weak'
    } else if (score <= 4) {
      level = 'medium'
    } else if (score <= 6) {
      level = 'strong'
    } else {
      level = 'very-strong'
    }

    return { score, level, suggestions }
  }

  // 生成安全随机数
  static generateSecureRandom(length: number = 16): string {
    const array = new Uint8Array(length)

    // #ifdef H5
    if (
      typeof window !== 'undefined' &&
      window.crypto &&
      window.crypto.getRandomValues
    ) {
      window.crypto.getRandomValues(array)
    } else {
      // 降级方案
      for (let i = 0; i < length; i++) {
        array[i] = Math.floor(Math.random() * 256)
      }
    }
    // #endif

    // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || APP-PLUS
    // 在小程序和App中使用Math.random作为降级方案
    for (let i = 0; i < length; i++) {
      array[i] = Math.floor(Math.random() * 256)
    }
    // #endif

    return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join(
      ''
    )
  }

  // 生成UUID v4
  static generateUUID(): string {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
      /[xy]/g,
      function (c) {
        const r = (Math.random() * 16) | 0
        const v = c === 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
      }
    )
  }
}

// XSS防护工具
export class XSSProtection {
  // HTML转义
  static escapeHtml(text: string): string {
    const map: Record<string, string> = {
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#39;',
      '/': '&#x2F;',
    }

    return text.replace(/[&<>"'/]/g, (s) => map[s])
  }

  // 移除HTML标签
  static stripHtml(html: string): string {
    return html.replace(/<[^>]*>/g, '')
  }

  // 验证和清理用户输入
  static sanitizeInput(
    input: string,
    options: {
      allowHtml?: boolean
      maxLength?: number
      allowedTags?: string[]
    } = {}
  ): string {
    const { allowHtml = false, maxLength = 1000, allowedTags = [] } = options

    // 长度限制
    let sanitized = input.slice(0, maxLength)

    if (!allowHtml) {
      // 转义HTML
      sanitized = this.escapeHtml(sanitized)
    } else if (allowedTags.length > 0) {
      // 只允许特定标签
      const allowedTagsRegex = new RegExp(
        `<(?!/?(?:${allowedTags.join('|')})\\b)[^>]*>`,
        'gi'
      )
      sanitized = sanitized.replace(allowedTagsRegex, '')
    }

    return sanitized
  }

  // 检测潜在的XSS攻击
  static detectXSS(input: string): boolean {
    const xssPatterns = [
      /<script[^>]*>.*?<\/script>/gi,
      /javascript:/gi,
      /on\w+\s*=/gi,
      /<iframe[^>]*>.*?<\/iframe>/gi,
      /<object[^>]*>.*?<\/object>/gi,
      /<embed[^>]*>.*?<\/embed>/gi,
      /<link[^>]*>.*?<\/link>/gi,
      /<meta[^>]*>.*?<\/meta>/gi,
      /<style[^>]*>.*?<\/style>/gi,
    ]

    return xssPatterns.some((pattern) => pattern.test(input))
  }
}

// 数据脱敏工具
export class DataMasking {
  // 手机号脱敏
  static maskPhone(phone: string): string {
    if (!phone || phone.length < 11) return phone
    return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
  }

  // 邮箱脱敏
  static maskEmail(email: string): string {
    if (!email || !email.includes('@')) return email
    const [username, domain] = email.split('@')
    if (username.length <= 2) return email
    const maskedUsername =
      username[0] +
      '*'.repeat(username.length - 2) +
      username[username.length - 1]
    return `${maskedUsername}@${domain}`
  }

  // 身份证号脱敏
  static maskIdCard(idCard: string): string {
    if (!idCard || idCard.length < 8) return idCard
    return idCard.replace(/(\d{4})\d{10}(\d{4})/, '$1**********$2')
  }

  // 银行卡号脱敏
  static maskBankCard(bankCard: string): string {
    if (!bankCard || bankCard.length < 8) return bankCard
    return bankCard.replace(/(\d{4})\d+(\d{4})/, '$1****$2')
  }

  // 姓名脱敏
  static maskName(name: string): string {
    if (!name || name.length <= 1) return name
    if (name.length === 2) return name[0] + '*'
    return name[0] + '*'.repeat(name.length - 2) + name[name.length - 1]
  }

  // 地址脱敏
  static maskAddress(address: string): string {
    if (!address || address.length < 6) return address
    const visibleLength = Math.min(6, Math.floor(address.length / 3))
    const start = address.slice(0, visibleLength)
    const end = address.slice(-visibleLength)
    const middle = '*'.repeat(address.length - visibleLength * 2)
    return start + middle + end
  }

  // 通用脱敏（保留前后几位）
  static maskString(
    str: string,
    keepStart: number = 3,
    keepEnd: number = 3,
    maskChar: string = '*'
  ): string {
    if (!str || str.length <= keepStart + keepEnd) return str
    const start = str.slice(0, keepStart)
    const end = str.slice(-keepEnd)
    const middle = maskChar.repeat(str.length - keepStart - keepEnd)
    return start + middle + end
  }
}

// 输入验证工具
export class InputValidator {
  // 验证手机号
  static validatePhone(phone: string): boolean {
    const phoneRegex = /^1[3-9]\d{9}$/
    return phoneRegex.test(phone)
  }

  // 验证邮箱
  static validateEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return emailRegex.test(email)
  }

  // 验证身份证号
  static validateIdCard(idCard: string): boolean {
    const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
    return idCardRegex.test(idCard)
  }

  // 验证URL
  static validateUrl(url: string): boolean {
    try {
      new URL(url)
      return true
    } catch {
      return false
    }
  }

  // 验证IP地址
  static validateIP(ip: string): boolean {
    const ipRegex =
      /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
    return ipRegex.test(ip)
  }

  // 验证密码
  static validatePassword(
    password: string,
    options: {
      minLength?: number
      requireUppercase?: boolean
      requireLowercase?: boolean
      requireNumbers?: boolean
      requireSpecialChars?: boolean
    } = {}
  ): { valid: boolean; errors: string[] } {
    const {
      minLength = 8,
      requireUppercase = true,
      requireLowercase = true,
      requireNumbers = true,
      requireSpecialChars = false,
    } = options

    const errors: string[] = []

    if (password.length < minLength) {
      errors.push(`密码长度至少${minLength}位`)
    }

    if (requireUppercase && !/[A-Z]/.test(password)) {
      errors.push('密码必须包含大写字母')
    }

    if (requireLowercase && !/[a-z]/.test(password)) {
      errors.push('密码必须包含小写字母')
    }

    if (requireNumbers && !/\d/.test(password)) {
      errors.push('密码必须包含数字')
    }

    if (requireSpecialChars && !/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
      errors.push('密码必须包含特殊字符')
    }

    return {
      valid: errors.length === 0,
      errors,
    }
  }

  // 验证用户名
  static validateUsername(username: string): {
    valid: boolean
    errors: string[]
  } {
    const errors: string[] = []

    if (username.length < 3) {
      errors.push('用户名长度至少3位')
    }

    if (username.length > 20) {
      errors.push('用户名长度不能超过20位')
    }

    if (!/^[a-zA-Z0-9_]+$/.test(username)) {
      errors.push('用户名只能包含字母、数字和下划线')
    }

    if (/^[0-9]/.test(username)) {
      errors.push('用户名不能以数字开头')
    }

    return {
      valid: errors.length === 0,
      errors,
    }
  }
}

// 导出所有工具
export default {
  SecurityUtils,
  XSSProtection,
  DataMasking,
  InputValidator,
}
